﻿using System;

namespace DynConDevCorp.OpenArch.SmartData.Interfaces
{

    /// <summary>
    /// Enumeration representing an aggregation of Booleans that may have inconsistent states.
    /// </summary>
    public enum PartialBooleanState
    {
        /// <summary>
        /// Internal Catch-All for Un-Initialized State
        /// </summary>
        Undefined = 0,

        /// <summary>
        /// Maps to Boolean.True
        /// </summary>
        True,

        /// <summary>
        /// Maps to Boolean.True
        /// </summary>
        False,

        /// <summary>
        /// Aggregated items are a mixture of states
        /// </summary>
        Mixed

    }

    /// <summary>
    /// Wrapper Struct for operations regarding multiple booleans.
    /// </summary>
    public struct PartialBoolean
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PartialBoolean"/> struct.
        /// </summary>
        /// <param name="state">The state.</param>
        public PartialBoolean(PartialBooleanState state)
        {
            m_State = state;
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(PartialBoolean value1, PartialBoolean value2)
        {
            return value1.Equals(value2);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="value1">The value1.</param>
        /// <param name="value2">The value2.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(PartialBoolean value1, PartialBoolean value2)
        {
            return !value1.Equals(value2);
        }

        /// <summary>
        /// Indicates whether this instance and a specified object are equal.
        /// </summary>
        /// <param name="obj">Another object to compare to.</param>
        /// <returns>
        /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (obj == null)
                return false;
            PartialBoolean other = (PartialBoolean)obj;
            return this == other;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PartialBoolean"/> struct.
        /// </summary>
        /// <param name="state">if set to <c>true</c> [state].</param>
        public PartialBoolean(bool state)
        {
            m_State = state ? PartialBooleanState.True : PartialBooleanState.False;
        }

        /// <summary>
        /// Gets the state.
        /// </summary>
        /// <value>The state.</value>
        public PartialBooleanState State { get { return m_State;}}

        /// <summary>
        /// Performs an implicit conversion from <see cref="System.Boolean"/> to <see cref="DynConDevCorp.OpenArch.SmartData.Interfaces.PartialBoolean"/>.
        /// </summary>
        /// <param name="state">if set to <c>true</c> [state].</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator PartialBoolean(bool state) { return new PartialBoolean(state); }

        /// <summary>
        /// Performs an explicit conversion from <see cref="DynConDevCorp.OpenArch.SmartData.Interfaces.PartialBoolean"/> to <see cref="System.Boolean"/>.
        /// </summary>
        /// <param name="value">The PartialBoolean Value (Must be a Valid Boolean State!).</param>
        /// <returns>The result of the conversion.</returns>
        public static explicit operator Boolean(PartialBoolean value)
        {
            switch (value.State)
            {
                case PartialBooleanState.True:
                    return true;
                case PartialBooleanState.False:
                    return false;
                default:
                    throw new ArgumentException("Source does not contain a valid Boolean State");
            }
        }

        /// <summary>
        /// Convert to Boolean.
        /// </summary>
        /// <returns></returns>
        public Boolean ToBoolean()
        {
            return (Boolean) this;
        }

        /// <summary>
        /// Gets the true.
        /// </summary>
        /// <value>The true.</value>
        public static PartialBoolean True {get{ return new PartialBoolean(true); }}

        /// <summary>
        /// Gets the false.
        /// </summary>
        /// <value>The false.</value>
        public static PartialBoolean False { get { return new PartialBoolean(false); } }

        /// <summary>
        /// Gets the mixed.
        /// </summary>
        /// <value>The mixed.</value>
        public static PartialBoolean Mixed {get { return new PartialBoolean(PartialBooleanState.Mixed);}}

        /// <summary>
        /// Gets a value indicating whether this instance is true.
        /// </summary>
        /// <value><c>true</c> if this instance is true; otherwise, <c>false</c>.</value>
        public bool IsTrue { get { return m_State == PartialBooleanState.True; } }

        /// <summary>
        /// Gets a value indicating whether this instance is false.
        /// </summary>
        /// <value><c>true</c> if this instance is false; otherwise, <c>false</c>.</value>
        public bool IsFalse { get { return m_State == PartialBooleanState.False; } }

        /// <summary>
        /// Gets a value indicating whether this instance is valid boolean.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is valid boolean; otherwise, <c>false</c>.
        /// </value>
        public bool IsValidBoolean { get { return IsTrue || IsFalse; } }
        
        private readonly PartialBooleanState m_State;

        /// <summary>
        /// Equalses the specified obj.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public bool Equals(PartialBoolean obj)
        {
            return Equals(obj.m_State, m_State);
        }

        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer that is the hash code for this instance.
        /// </returns>
        public override int GetHashCode()
        {
            return m_State.GetHashCode();
        }
    }

    /// <summary>
    /// Eumeration for tracking the current state of an item with respect to its persisted information.
    /// </summary>
    public enum SmartPersistenceState
    {
        /// <summary>
        /// Item is NOT persisted, and does not require coordination.
        /// </summary>
        NonPersisting,
        /// <summary>
        /// Item is capable of being persisted, but is "new" and has not yet been persisted.
        /// </summary>
        NewItem,
        /// <summary>
        /// Item has been persisted, and has not been modified since. This is the only value where
        /// the object state and persisted state are guaranteed to be identical.
        /// </summary>
        Persisted,
        /// <summary>
        /// Item has been persisted, but has been modified since that time.
        /// </summary>
        ChangesPending
    }

    /// <summary>
    /// Various Value Tracking States for Smart Items.
    /// </summary>
    public enum TrackingMode
    {
        /// <summary>
        /// Value Tracking is Not Supported
        /// </summary>
        NotTracking,

        /// <summary>
        /// Value has Been Changed from last Commit() or Rollback()
        /// </summary>
        Dirty,

        /// <summary>
        /// Value has NOT been Changed from last Commit() or Rollback()
        /// </summary>
        Committed
    }


    /// <summary>
    /// Helper Enumerator to differentiaty the category of Smart object that is contained in the collection.
    /// </summary>
    public enum CollectionClassCategory
    {
        /// <summary>
        /// Collection item type is Unknown
        /// </summary>
        Unknown,
        /// <summary>
        /// Collection item type is derived from ISmartField, but NOT from any more specific enumeration. 
        /// All more specific enumerated values will be greater than this value.
        /// </summary>
        Field,
        /// <summary>
        /// Collection item type is derived from ISmartEntity
        /// </summary>
        Entity
    }

    /// <summary>
    /// Enumeration which containst the type of change that is being reported by event arguments.
    /// </summary>
    public enum CollectionChangeType
    {
        /// <summary>
        /// Unknown type of change. Should not occur!
        /// </summary>
        Unknown,
        /// <summary>
        /// Collection has just been cleared.
        /// </summary>
        Clear,
        /// <summary>
        /// Item has just been added to collection.
        /// </summary>
        Add,
        /// <summary>
        /// Item has just been removed from collection.
        /// </summary>
        Remove,
        /// <summary>
        /// Item in collection has just had one (or more) Values changed.
        /// </summary>
        Change
    }


}